package com.ccteam.fluidmusic.ui.moment.comment

import androidx.lifecycle.*
import androidx.paging.LoadState
import androidx.paging.cachedIn
import com.ccteam.fluidmusic.utils.setValueIfNew
import com.ccteam.fluidmusic.view.bean.ErrorMessage
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.model.Resource
import com.ccteam.network.ApiError
import com.ccteam.shared.domain.moment.comment.CommentListDataUseCase
import com.ccteam.shared.domain.moment.comment.MomentParentCommentDataUseCase
import com.ccteam.shared.result.moment.comment.MomentCommentItem
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * @author Xiaoc
 * @since 2021/3/29
 *
 * 查看更多评论所用的ViewModel
 */
@HiltViewModel
class CommentsViewModel @Inject constructor(
    private val momentParentCommentDataUseCase: MomentParentCommentDataUseCase,
    commentListDataUseCase: CommentListDataUseCase,
    savedStateHandle: SavedStateHandle
): ViewModel() {

    private val _parentCommentList = MutableLiveData<List<MomentCommentItem>>()
    val parentCommentList: LiveData<List<MomentCommentItem>> get() = _parentCommentList

    val commentList = commentListDataUseCase(savedStateHandle["parentCommentId"])
        .cachedIn(viewModelScope)

    private val _loadMessage = MediatorLiveData<LoadMessage>()
    val loadMessage: LiveData<LoadMessage> get() = _loadMessage

    private val parentCommentId = MutableLiveData<String>()

    private val replayLoadMessage = MutableLiveData<LoadMessage>()
    private val parentCommentLoadMessage = MutableLiveData<LoadMessage>()

    init {

        _loadMessage.addSource(parentCommentId){
            refreshParentCommentInfo()
        }

        parentCommentId.setValueIfNew(savedStateHandle["parentCommentId"])

        _loadMessage.addSource(replayLoadMessage){
            _loadMessage.value = checkLoadMessage(it,parentCommentLoadMessage.value)

        }
        _loadMessage.addSource(parentCommentLoadMessage){
            _loadMessage.value = checkLoadMessage(it,replayLoadMessage.value)
        }

    }

    fun refreshParentCommentInfo(){
        parentCommentId.value?.let {
            viewModelScope.launch {
                val result = momentParentCommentDataUseCase(it)
                if(result is Resource.Success){
                    parentCommentLoadMessage.value = LoadMessage.NotLoading
                    _parentCommentList.value = result.data ?: emptyList()
                } else {
                    parentCommentLoadMessage.value = LoadMessage.Error(ErrorMessage(result.message,result.errorCode))
                }
            }
        }
    }

    fun setLoadMessage(states: LoadState){
        when (states) {
            is LoadState.Loading -> {
                replayLoadMessage.value = LoadMessage.Loading
            }
            is LoadState.Error -> {
                replayLoadMessage.value = LoadMessage.Error(ErrorMessage(states.error.message,ApiError.unknownCode))
            }
            else -> {
                replayLoadMessage.value = LoadMessage.NotLoading
            }
        }
    }

    private fun checkLoadMessage(selfLoadMessage: LoadMessage?,otherLoadMessage: LoadMessage?): LoadMessage{
        return when{
            selfLoadMessage is LoadMessage.Loading || otherLoadMessage is LoadMessage.Loading ->{
                LoadMessage.Loading
            }
            selfLoadMessage is LoadMessage.Error ->{
                LoadMessage.Error(ErrorMessage(selfLoadMessage.errorMessage.description,selfLoadMessage.errorMessage.errorCode))
            }
            otherLoadMessage is LoadMessage.Error ->{
                LoadMessage.Error(ErrorMessage(otherLoadMessage.errorMessage.description,otherLoadMessage.errorMessage.errorCode))
            }
            selfLoadMessage is LoadMessage.NotLoading && otherLoadMessage is LoadMessage.NotLoading ->{
                LoadMessage.NotLoading
            }
            else ->{
                LoadMessage.Error(ErrorMessage())
            }
        }
    }
}